<?php

namespace app\common\service;

use app\common\model\RuinuoVerify;
use think\facade\Cache;
use think\facade\Db;

class Validate
{

    public function VerifyData()
    {
        $CacheId = 'ruinuo_verify';
        if (Cache::get($CacheId)) {
            $Rule = Cache::get($CacheId);
        } else {
            $RuinuoVerify = new RuinuoVerify();
            $Verify = $RuinuoVerify->field("name,num,guize")->select()->toArray();
            $Rule = [];
            foreach ($Verify as $k => $v) {
                $Rule[strtolower($v['num'])] = [
                    'title' => $v['name'],
                    'rule' => $v['guize'],
                ];
            }
            $Rule['required'] = [
                'title' => '必填',
                'rule' => '/\S+/',
            ];
            Cache::set($CacheId, $Rule, 600);
        }
        return $Rule;
    }


    public function Rule($rule, $data, $Model, $InfoMode, $id = '')
    {
        $GuiZe = $this->VerifyData();
        $rules = [];
        foreach ($data as $k => $v) {
            $table = $k;
            foreach ($v as $k2 => $v2) {
                $field = $k2;
                foreach ($rule as $kk => $vv) {
                    if ($table == $vv['table'] && $field == $vv['field']) {
                        $vv['value'] = isset($data[$vv['table']][$vv['field']]) ? $data[$vv['table']][$vv['field']] : '';
                        $rules[] = $vv;
                    }
                }
            }
        }

        foreach ($rules as $k => $v) {
            $value = $v['value'];
            $v['rule'] = strtolower($v['rule']);
            if ($v['rule'] == 'required' && $value == '[]') {
                $value = '';
            }
            if ($v['tag'] == 'subtable') {
                $value = Db::name($v['value']['database'])->where("" . $v['value']['sub_id'] . "='" . $v['value']['value'] . "'")->count();
                if (empty($value)) {
                    $value = "";
                }
                $v['field'] = "sub__" . $v['field'];
            }
            $BackData['field'] = $v['field'];
            if ($v['table'] != "a") {
                $BackData['field'] = $v['table'] . "__" . $v['field'];
            }
            $check = $this->VerifyCheck($value, $v['rule'], $GuiZe);
            if (!$check) {
                $title = ',只能是' . $GuiZe[$v['rule']]['title'] . '格式';
                if ($v['rule'] == 'required') {
                    $title = "";
                }
                return ['code' => 203, 'msg' => $v['msg'] . $title, 'data' => $BackData];
            }
            if ($v['rule'] == 'cols') {//验证Json
                $CheckData = $this->JsonCheck($value, $v, $GuiZe);
                if ($CheckData['code'] != 200) {
                    return $CheckData;
                }
            }
            if ($v['rule'] == 'only') {//验证唯一值
                $check = $this->OnlyCheck($InfoMode, $Model, $id, $value, $v);
                if (!$check) {
                    return ['code' => 203, 'msg' => $v['msg'], 'data' => $BackData];
                }
            }
        }
        return ['code' => 200];
    }

    public function OnlyCheck($InfoMode, $Model, $id, $value, $item)
    {
        $sub_database = $InfoMode['sub_database'];
        $tables = [];
        foreach ($sub_database as $k => $v) {
            $tables[$v['alias']] = $v;
        }
        $where = "" . $item['field'] . "='" . $value . "'";
        if ($item['table'] != 'a') {
            $base = $tables[$item['table']];
            if ($id) {
                $find = $Model->where("id='" . $id . "'")->find();
                if ($base['type'] == 1) {
                    $where .= " and " . $base['sub_field'] . "!='" . $find[$base['key_field']] . "'";//正向关联
                } else {
                    $where .= " and " . $base['key_field'] . "!='" . $find[$base['sub_field']] . "'";;//反向关联
                }
            }
            $Db = Db::name($base['database']);
        } else {
            if ($id) {
                $where .= " and id!='" . $id . "'";
            }
            $Db = $Model;
        }
        $count = $Db->where($where)->count();
        if ($count >= 1) {
            return false;
        }
        return true;
    }

    public function JsonCheck($value, $items, $validate)
    {
        $value = !empty($value) ? json_decode($value, true) : [];
        $colsField = [];
        foreach ($items['cols'] as $k2 => $v2) {
            $colsField[$v2['field']] = $v2;
        }
        foreach ($value as $k2 => $v2) {
            foreach ($v2 as $k3 => $v3) {
                if (isset($colsField[$k3])) {
                    $item = $colsField[$k3];
                    $required = !empty($item['required']) ? $item['required'] : 2;
                    $BackData = ['field' => $items['field'] . '||' . $item['field'] . '||' . $k2];
                    $val = isset($v2[$k3]) ? $v2[$k3] : '';
                    if ($required == 1 && $val == '') {
                        return ['code' => 203, 'msg' => $item['title'] . '必填', 'data' => $BackData];
                    }
                    $verify = !empty($item['verify']) ? strtolower($item['verify']) : '';
                    if ($verify) {
                        $check = $this->VerifyCheck($val, $verify, $validate);
                        if (!$check) {
                            $title = ',只能是' . $validate[$verify]['title'] . '格式';
                            return ['code' => 203, 'msg' => $item['title'] . '填写错误' . $title, 'data' => $BackData];
                        }
                    }
                }
            }
        }
        return ['code' => 200];
    }

    public function VerifyCheck($value, $rule, $validate = [])
    {
        if ($value == '' && $rule != 'required') {
            return true;
        }
        if (isset($validate[$rule])) {
            $rule = $validate[$rule]['rule'];
            if (preg_match($rule, $value)) {
                return true;
            } else {
                return false;
            }
        }
        return true;
    }
}